package com.tiance.domainservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.tiance.constants.CommonConstants;
import com.tiance.dal.dao.*;
import com.tiance.dal.dataobject.*;
import com.tiance.domainservice.assemble.DOAssemble;
import com.tiance.domainservice.checker.MemberParamsChecker;
import com.tiance.domainservice.domain.IntegrationDomain;
import com.tiance.domainservice.domain.MemberAuthenticationInfoDomain;
import com.tiance.domainservice.domain.MemberDomain;
import com.tiance.domainservice.service.IntegrationService;
import com.tiance.domainservice.service.MemberService;
import com.tiance.domainservice.utils.MemberUtil;
import com.tiance.enums.*;
import com.tiance.exception.BusinessException;
import com.tiance.integration.config.CommonProperties;
import com.tiance.integration.idcard.IDCardUtil;
import com.tiance.integration.wechat.WechatClient;
import com.tiance.integration.wechat.WxUserInfo;
import com.tiance.page.QueryPage;
import com.tiance.utils.BeanConverterUtil;
import com.tiance.utils.MapUtil;
import com.tiance.utils.StringUtil;
import com.tiance.utils.Validator;
import com.tiance.vo.ImageVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author 雷霆
 * @version 1.0.0
 * @date$ 2019/2/4
 *
 * Description：
 *
 * Modification History:
 *
 */
@Service
public class MemberServiceImpl implements MemberService {

    /** logger */
    protected static final Logger logger = LoggerFactory.getLogger(MemberServiceImpl.class);

    @Resource
    private MemberDAO memberDAO;

    @Resource
    private MemberAuthenticationInfoDAO memberAuthenticationInfoDAO;
    @Resource
    private MemberAuthFileDAO           memberAuthFileDAO;
    @Resource
    private MemberAuthOpinionDAO        memberAuthOpinionDAO;




    @Autowired
    private IntegrationService integrationService;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Long register(MemberDomain memberDomain)throws Exception {
        MemberDO recommondMemberDO=null;
        if(!StringUtils.isEmpty(memberDomain.getRecommendMemberNo())){
            Map<String,Object> map= MapUtil.params2Map(
                    new Object[]{"memberNo",StringUtil.trimNull(memberDomain.getRecommendMemberNo())});
            logger.info("开始查询推荐人是否存在，参数:{}", JSON.toJSONString(map));
            recommondMemberDO=memberDAO.queryMember(map);
            logger.info("结束查询推荐人是否存在，返回数据:{}", JSON.toJSONString(recommondMemberDO));
            Validator.assertNull(recommondMemberDO,"请输入正确的推荐人会员号!");
            Validator.assertNull(recommondMemberDO.getId(),"请输入正确的推荐人会员号!");

        }
        MemberDO memberDO= DOAssemble.assembleMemberDO(memberDomain);
        memberDO.setMemberCardNo(MemberUtil.generateMemberCardNo());
        memberDO.setMemberNo(MemberUtil.generateMemberNo());
        logger.info("开始更新会员数据，参数:{}", JSON.toJSONString(memberDO));

        Long count=memberDAO.registerMember(memberDO);
        memberDomain.setId(memberDO.getId());
        logger.info("结束更新会员数据，是否更新成功:{}", count>0?true:false);
        if(count<1){
            throw new BusinessException("更新失败");
        }

        //会员增加积分
        IntegrationDomain integrationDomain=new IntegrationDomain();
        integrationDomain.setIntegrationType(IntegrationTypeEnum.INTEGRATION.getCode());
        integrationDomain.setMemberId(memberDO.getId());
        integrationDomain.setBelongType(IntegrationBelongTypeEnum.MEMBER.getCode());
        integrationDomain.setIntegrationRuleCode(IntegrationRuleCodeEnum.MEMBER_REGISTER_SUCCESS);
        integrationService.addIntegration(true,integrationDomain);

        //推荐人增加积分
        if(null!=recommondMemberDO){
            integrationDomain.setMemberId(recommondMemberDO.getId());
            integrationDomain.setBelongType(IntegrationBelongTypeEnum.REFERRER.getCode());
            integrationService.addIntegration(false,integrationDomain);
        }

        return memberDO.getId();

    }

    @Override
    public MemberDO queryMember(MemberDomain memberDomain) {
        Map<String,Object> map= MapUtil.params2Map(new Object[]{ "id", StringUtil.trimNull(memberDomain.getId())},
                new Object[]{ "memberCardNo", StringUtil.trimNull(memberDomain.getMemberCardNo())},
                new Object[]{"memberNo",StringUtil.trimNull(memberDomain.getMemberNo())},
                new Object[]{"openid",StringUtil.trimNull(memberDomain.getOpenid())},
                new Object[]{"phone",StringUtil.trimNull(memberDomain.getPhone())});

        logger.info("开始查询会员数据，参数:{}", JSON.toJSONString(map));
        MemberDO memberDO=memberDAO.queryMember(map);
        logger.info("结束查询会员数据，返回数据:{}", JSON.toJSONString(memberDO));
        return memberDO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public MemberDO updateMember(MemberDomain memberDomain) throws Exception{
        MemberDO memberDO=new MemberDO();
        BeanConverterUtil.copyProperties(memberDO,memberDomain);
        logger.info("开始更新会员数据，参数:{}", JSON.toJSONString(memberDO));
        Long memberId=memberDAO.updateMember(memberDO);
        logger.info("结束更新会员数据，是否更新成功:{}", memberId>0?true:false);
        Map<String,Object> map= MapUtil.params2Map(new Object[]{"id",StringUtil.trimNull(memberDomain.getId())});
        memberDO=memberDAO.queryMember(map);

        return memberDO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void applyMemberAuth(MemberAuthenticationInfoDomain domain)
            throws Exception {

        if(!InfoTypeEnum.ALL_INFO.getCode().equals(domain.getInfoType())){
            MemberAuthenticationInfoDO memberAuthenticationInfoDO= DOAssemble.assembleMemberAuthenticationInfoDO(domain);
            logger.info("开始插入会员认证数据，参数:{}", JSON.toJSONString(memberAuthenticationInfoDO));
            try {
                Long count = memberAuthenticationInfoDAO.insert(memberAuthenticationInfoDO);
                logger.info("结束插入会员认证数据，是否插入成功:{}", count>0?true:false);
                if(count<1){
                    throw new BusinessException("插入失败");
                }
            }catch (DuplicateKeyException e){
                logger.info("会员认证数据已存在，准备更新");
                Long count = memberAuthenticationInfoDAO.update(memberAuthenticationInfoDO);
                logger.info("会员认证数据已存在，准备更新，是否更新成功:{}", count>0?true:false);
                if(count<1){
                    throw new BusinessException("更新失败");
                }

            }

            this.insertAuthFile(domain,memberAuthenticationInfoDO.getId(),domain.getIdCardBackUrl(),"",AuthFileTypeEnum.ID_CARD_BACK);
            this.insertAuthFile(domain, memberAuthenticationInfoDO.getId(), domain.getIdCardFrontUrl(),"",AuthFileTypeEnum.ID_CARD_FRONT);
            this.insertAuthFile(domain, memberAuthenticationInfoDO.getId(), domain.getChooseJobCertificateUrl(),"", AuthFileTypeEnum.CHOOSE_JOB_CERTIFICATE);
            this.insertAuthFile(domain, memberAuthenticationInfoDO.getId(), domain.getRetirementResumeCertificateUrl(),"",AuthFileTypeEnum.RETIREMENT_RESUME_CERTIFICATE);
            if(!CollectionUtils.isEmpty(domain.getJobQualificationCertificateList())){
                for(ImageVO imageVO:domain.getJobQualificationCertificateList()){
                    this.insertAuthFile(domain, memberAuthenticationInfoDO.getId(), imageVO.getUrl(),imageVO.getName(),AuthFileTypeEnum.JOB_QUALIFICATION_CERTIFICATE);
                }
            }

            return;
        }

        Map<String,Object> map= MapUtil.params2Map(new Object[]{ "memberId", domain.getMemberId()});
        logger.info("开始查询会员认证数据，参数:{}", JSON.toJSONString(map));
        MemberAuthenticationInfoDO memberAuthenticationInfoDO=memberAuthenticationInfoDAO.queryMemberAuthApplyDetail(map);
        logger.info("结束查询会员认证数据，返回数据:{}", JSON.toJSONString(memberAuthenticationInfoDO));

        MemberParamsChecker.checkMemberAuth(memberAuthenticationInfoDO);
        map.put("authenticationInfoId",memberAuthenticationInfoDO.getId());
        logger.info("开始查询会员认证材料数据，参数:{}", JSON.toJSONString(map));
        List<MemberAuthFileDO> memberAuthFileList=memberAuthFileDAO.queryMemberAuthFileList(map);
        logger.info("结束查询会员认证材料数据，返回数据:{}", JSON.toJSONString(memberAuthFileList));
        MemberParamsChecker.checkFiles(memberAuthenticationInfoDO,memberAuthFileList);

        MemberDO memberDO=new MemberDO();
        memberDO.setId(domain.getMemberId());
        memberDO.setMemberStatus(MemberStatusEnum.VERIFY_APPLIED.getCode());



        MemberAuthOpinionDO memberAuthOpinionDO=new MemberAuthOpinionDO();
        memberAuthOpinionDO.setMemberId(domain.getMemberId());
        memberAuthOpinionDO.setAuthUserId(1L);
        memberAuthOpinionDO.setAuthUserName("admin");
        memberAuthOpinionDO.setOpenid(memberAuthenticationInfoDO.getOpenid());
        memberAuthOpinionDO.setAuthenticationInfoId(memberAuthenticationInfoDO.getId());
        try {

          IDCardUtil.verifyIdCardInfo(memberAuthenticationInfoDO.getIdNumber(),memberAuthenticationInfoDO.getRealName());
          memberAuthOpinionDO.setAuthState(MemberAuthStatusEnum.ID_CARD_VERIFY_SUCCESS.getCode());
          memberAuthOpinionDO.setAuthOpinion1("身份证认证通过");
        }catch (Exception e){
            memberDO.setMemberStatus(MemberStatusEnum.BACKGROUND_VERIFY_FAIL.getCode());
            memberDO.setRemark(e.getMessage());

            memberAuthOpinionDO.setAuthState(MemberAuthStatusEnum.ID_CARD_VERIFY_FAIL.getCode());
            memberAuthOpinionDO.setAuthOpinion1(e.getMessage());

        }


        logger.info("开始更新会员数据，参数:{}", JSON.toJSONString(memberDO));
        Long count=memberDAO.updateMember(memberDO);
        logger.info("结束更新会员数据，是否更新成功:{}", count>0?true:false);


        logger.info("开始插入会员认证数据，参数:{}", JSON.toJSONString(memberAuthOpinionDO));
        Long memberAuthOpinionCount=memberAuthOpinionDAO.insert(memberAuthOpinionDO);
        logger.info("结束插入会员数据，是否插入成功:{}", memberAuthOpinionCount>0?true:false);



        //调整会员积分
        logger.info("开始调整会员积分，参数:{}", JSON.toJSONString(memberAuthOpinionDO));
        IntegrationDomain integrationDomain=new IntegrationDomain();
        integrationDomain.setIntegrationType(IntegrationTypeEnum.INTEGRATION.getCode());
        integrationDomain.setMemberId(memberDO.getId());
        integrationDomain.setBelongType(IntegrationBelongTypeEnum.MEMBER.getCode());
        integrationDomain.setIntegrationRuleCode(IntegrationRuleCodeEnum.MEMBER_VERIFY_APPLIED);
        integrationService.addIntegration(true,integrationDomain);

        logger.info("开始查询会员推荐人，参数:{}", memberDO.getId());
        Long recommendMemberId=memberDAO.queryRecommendMemberId(memberDO.getId());
        logger.info("结束查询会员推荐人，参数:{}", JSON.toJSONString(memberAuthOpinionDO));

        if(null!=recommendMemberId){
            //调整推荐人会员积分
            logger.info("开始调整推荐人会员积分，参数:{}", JSON.toJSONString(memberAuthOpinionDO));
            integrationDomain=new IntegrationDomain();
            integrationDomain.setMemberId(recommendMemberId);
            integrationDomain.setBelongType(IntegrationBelongTypeEnum.REFERRER.getCode());
            integrationDomain.setIntegrationRuleCode(IntegrationRuleCodeEnum.MEMBER_VERIFY_APPLIED);
            integrationService.addIntegration(false,integrationDomain);
        }


    }

    @Override
    public List<MemberDO> queryMemberList(MemberDomain domain) {

        Map<String,Object> paramMap= MapUtil.params2Map(new Object[]{ "memberId", StringUtil.trimNull(domain.getMemberId())},
                new Object[]{ "id", StringUtil.trimNull(domain.getId())},
                new Object[]{ "wxNickName", StringUtil.trimNull(domain.getWxNickName())},
                new Object[]{ "realName", StringUtil.trimNull(domain.getRealName())},
                new Object[]{ "memberType", StringUtil.trimNull(domain.getMemberType())},
                new Object[]{ "openid", StringUtil.trimNull(domain.getOpenid())});
        logger.info("开始查询会员总数，参数:{}", JSON.toJSONString(paramMap));
        int count  =memberDAO.queryMemberListCount(paramMap);
        logger.info("开始查询会员总数，返回总数:{}", count);


        if(0==count){
            return new ArrayList();
        }

        QueryPage queryPage = domain.getQueryPage();
        queryPage.setTotalItem(count);
        paramMap.put("queryPage", queryPage);
        if (queryPage.getEndRow() == 0) {
            queryPage.setStartRow(queryPage.getPageFristItem());
            queryPage.setEndRow(queryPage.getPageLastItem());
        }

        domain.setQueryPage(queryPage);
        logger.info("开始查询会员列表数据，参数:{}", JSON.toJSONString(paramMap));
        List<MemberDO> memberDOList =memberDAO.queryMemberList(paramMap);
        logger.info("结束查询会员列表数据，查询结果:{}", JSON.toJSONString(memberDOList));
        return memberDOList;
    }

    @Override
    public void addGuest(MemberDomain memberDomain) {
        try{
            MemberDO memberDO=new MemberDO();
            BeanConverterUtil.copyProperties(memberDO,memberDomain);
            memberDO.setMemberType(MemberTypeEnum.GUEST.getCode());
            logger.info("开始插入游客数据，参数:{}", JSON.toJSONString(memberDO));
            Long count=memberDAO.insert(memberDO);
            memberDomain.setId(memberDO.getId());
            logger.info("结束插入游客数据，是否插入成功:{}", count>0?true:false);
            if(count<1){
                throw new BusinessException("插入失败");
            }
        }catch (DuplicateKeyException e){
            String messageInfo= e.getCause().getMessage();
            if(messageInfo.contains("OPENID")){
                throw new BusinessException("该OPENID已存在!");
            }else if(messageInfo.contains("PHONE")){
                throw new BusinessException("该手机号已存在!");
            }
            logger.info("插入游客数据异常:{}", e);
        }catch (Exception e){

        }


    }


    private void insertAuthFile(MemberAuthenticationInfoDomain domain, Long id, String filePath,String fileName,
                                AuthFileTypeEnum fileType) throws Exception {
        if(StringUtils.isEmpty(filePath)){
            return;
        }
        String fileFormat = filePath.substring(filePath.lastIndexOf(".") +1);
        MemberAuthFileDO memberAuthFileDO = DOAssemble.assembleMemberAuthFileDO(fileFormat,fileName,filePath,fileType.getMsg(),fileType.getCode());
        memberAuthFileDO.setMemberId(domain.getMemberId());
        memberAuthFileDO.setOpenid(domain.getOpenid());
        memberAuthFileDO.setAuthenticationInfoId(id);
        logger.info("开始插入会员认证文件，参数:{}", JSON.toJSONString(memberAuthFileDO));
        Long filecount= memberAuthFileDAO.insert(memberAuthFileDO);
        logger.info("结束插入会员认证文件，是否插入成功:{}", filecount>0?true:false);
        if(filecount<1){
            throw new BusinessException("插入失败");
        }
    }
}
